#ifndef _470BOT_H
#define _470BOT_H

#define _CRT_SECURE_NO_DEPRECATE 1
#define _USE_MATH_DEFINES

#include <WinSock2.h>
#include <string.h>
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <string>
#include <windows.h>

#include "math.h"
#include "Command.h"
#include "World.h"

using namespace std;

#define MAX_OBSTACLE_CORNERS 10
const int kBufferSize = 1024;

typedef struct team_t {
	string color;
	int count;
	double base_corner[4][2];
} team_t;

typedef struct obstacle_t {
	double o_corner[MAX_OBSTACLE_CORNERS][2];
	short size;
} obstacle_t;

typedef struct flag_t {
	string color;
	string poss_color;
	double pos[2];
} flag_t;

typedef struct shot_t {
	double pos[2];
	double velocity[2];
} shot_t;

typedef struct tank_t {
	int index;
	string callsign;
	string status;
	int shots_avail;
	double time_to_reload;
	string flag;
	double pos[2];
	double angle;
	double velocity[2];
	double angvel;
} tank_t;

typedef struct otank_t {
	string callsign;
	string color;
	string status;
	string flag;
	double pos[2];
	double angle;
} otank_t;

typedef struct constant_t {
	string name;
	string value;
} constant_t;

typedef struct occgrid_t {
	int dimensions[2];
	int topCorner[2];
	std::vector<string> grid;
} occgrid_t;

class SplitString {
	vector <string> MyVector;
	string MyString;
public:
	SplitString(string str) {
		MyString=str;
		MyVector.begin();
	}

	vector <string> Split() {
		MyVector.clear();
		size_t LastLoc = -1;
		size_t CurLoc = MyString.find(" ", 0);
		while (CurLoc != string::npos) {
			MyVector.push_back(MyString.substr(LastLoc+1, CurLoc-LastLoc-1));
			LastLoc=CurLoc;
			CurLoc = MyString.find(" ", LastLoc+1);
		}
		MyVector.push_back(MyString.substr(LastLoc+1, MyString.size()-LastLoc));
		return MyVector;
	}
};

class BZRC {
	const char *pcHost;
	int nPort;
	bool debug;
	bool InitStatus;
	char ReplyBuffer[kBufferSize];
	int LineFeedPos;
	int Start;

	SOCKET sd;

	// Initializing connection.
	int Init() {
		ResetReplyBuffer();
		Start=0;

		//debug=true;

		// Start Winsock up
		if(int nCode = WinSockInit() != 0) {
			cerr << "WSAStartup() returned error code " << nCode << "." << endl;
			return 1;
		}

		// Find the server's address
		u_long nRemoteAddress = LookupAddress(pcHost);
		if(nRemoteAddress == INADDR_NONE) {
			cerr << "Host cannot be found." << endl;
			return 1;
		}

		// Connect to the server
		sd = EstablishConnection(nRemoteAddress, htons(nPort));
		if(sd == INVALID_SOCKET) {
			cerr << WSAGetLastError() << endl;
			return 1;
		}


		if(HandShake()==1) {
			cerr << "Handshake failed!" << endl;
			return 1;
		}

		return 0;		
	}

	// Initialize WinSock
	int WinSockInit() {
		LPWSADATA lpmyWSAData;
		WORD VersionReqd;
		VersionReqd = MAKEWORD(2,0);
		lpmyWSAData = (LPWSADATA)malloc(sizeof(WSADATA));
		int Status = WSAStartup(VersionReqd, lpmyWSAData);
		if(Status != 0) return 0;
		if(LOBYTE(lpmyWSAData->wVersion) != 2 || HIBYTE(lpmyWSAData->wVersion) != 0) {
			WSACleanup();
			free(lpmyWSAData);
			return 0;
		}
		free(lpmyWSAData);
		return Status;
	}

	// Lookup IP address
	u_long LookupAddress(const char *pcHost) {
			u_long nRemoteAddr = inet_addr(pcHost);
			if (nRemoteAddr == INADDR_NONE) {
				// pcHost isn't a dotted IP, so resolve it through DNS
				hostent* pHE = gethostbyname(pcHost);
				if (pHE == 0) {
					return INADDR_NONE;
				}
				nRemoteAddr = *((u_long*)pHE->h_addr_list[0]);
			}
			return nRemoteAddr;
		}

	// Establish connection
	SOCKET EstablishConnection(u_long nRemoteAddr, u_short nPort) {
		// Create a stream socket
		SOCKET MySocket = socket(AF_INET, SOCK_STREAM, 0);
		if (MySocket != INVALID_SOCKET) {
			sockaddr_in sinRemote;
			sinRemote.sin_family = AF_INET;
			sinRemote.sin_addr.s_addr = nRemoteAddr;
			sinRemote.sin_port = nPort;
			if (connect(MySocket, (sockaddr*)&sinRemote, sizeof(sockaddr_in)) == SOCKET_ERROR) {
				MySocket = INVALID_SOCKET;
			}

			//unsigned long non_blocking = 1;
			//ioctlsocket (MySocket, FIONBIO, &non_blocking);
		}
		return MySocket;
	}

	// Send line to server
	int SendLine(const char *LineText) {
		int Length=(int)strlen(LineText);
		char Command[kBufferSize];
		strcpy(Command, LineText);
		Command[Length]='\n';
		Command[Length+1]='\0';
		if(debug)
			cout << Command;
		if (send(sd, Command, Length+1, 0) >= 0) {
			return 0;
		}
		else {
			return 1;
		}
	}
	// Read line back from server
	int ReadReply(char *Reply)
	{
		//char acReadBuffer[kBufferSize];

		long t1 = timer();
		int nNewBytes = recv(sd, /*acReadBuffer*/Reply, kBufferSize, 0);
		long t2 = timer();
		//std::cout << "read " << nNewBytes << " in " << t2-t1 << std::endl;
		if (nNewBytes < 0) {
			return -1;
		}
		else if (nNewBytes == 0) {
			cerr << "Connection closed by peer." << endl;
			return 0;
		}
		
		//memcpy(Reply, &acReadBuffer, nNewBytes);
		if(nNewBytes!=kBufferSize) {
			Reply[nNewBytes]='\0';
		}

		return nNewBytes;
	}

	// Only read one line of text from ReplyBuffer
	void ReadLine(char *LineText) {
		memset(LineText, '\0', kBufferSize);
		// Only read more from server when done wiht current ReplyBuffer
		
		//cout<<"Begin readLine" << endl;
		if(strlen(ReplyBuffer)==0) {
			char *Reply;
			Reply = ReplyBuffer;
			ReadReply(Reply);
		}
		int i=0;
		bool done=false;
		while(!done) {
			for(i=LineFeedPos+1; (i<kBufferSize && ReplyBuffer[i]); i++) {
				if(ReplyBuffer[i]=='\n') {
					//std::cout << "hello1" << std::endl;
					LineText[i-LineFeedPos-1+Start]='\0';
					LineFeedPos=i;
					Start=0;
					done=true;
					break;
				}
				LineText[i-LineFeedPos-1+Start]=ReplyBuffer[i];
			}
			if(!done) {
					//std::cout << "hello2" << std::endl;
					
					Start = (int)strlen(LineText);
					
					ResetReplyBuffer();	
					
					char *Reply;
					Reply = ReplyBuffer;
					
					long t1 = timer();
					ReadReply(Reply);
					long t2 = timer();
					//std::cout << "ReadReply " << t2 - t1 << std::endl;
			}
			else {
				if(ReplyBuffer[i]=='\0') {
					//std::cout << "hello3" << std::endl;
					
					done=true;
					Start=0;
					ResetReplyBuffer();
				}
			}
		}
	}

	// Reset the ReplyBuffer
	void ResetReplyBuffer() {
		memset(ReplyBuffer, '\0', kBufferSize);
		LineFeedPos=-1;
	}

	// Perform HandShake with the server
	int HandShake() {
		char str[kBufferSize];
		char *LineText;
		LineText=str;
		ReadLine(LineText);
		if(debug) cout << LineText << endl;
		if (!strcmp(LineText, "bzrobots 1")) {
			const char * Command="agent 1";
			int temp=SendLine(Command);
			if(temp==1) 
				return 1;
			else
				ResetReplyBuffer();
				return 0;
		}
		else
			return 1;
	}

	// Read line into vector
	vector <string> ReadArr() {
		char str[kBufferSize];
		char *LineText=str;
		
		ReadLine(LineText);
		//std::cout << "Line Read" << std::endl;
		if(strlen(LineText)!=0) {
			if(debug) cout << LineText << endl;
		}
		while(strlen(LineText)==0) {
			ReadLine(LineText);
			if(debug) cout << LineText << endl;
		}
		
		SplitString ss=SplitString(LineText);

		return ss.Split();
	}
	// Read Acknowledgement
	void ReadAck() {
		vector <string> v=ReadArr();
		if(v.at(0)!="ack") {
			cout << "Didn't receive ack! Exit!" << endl;
			exit(1);
		}
	}
	// Read "ok"
	bool ReadBool() {
		vector <string> v=ReadArr();
		if(v.at(0)=="ok") {
			return true;
		}
		else if(v.at(0)=="fail"){
			if(debug) cout << "Received fail. Exiting!" << endl;
			return false;
		}
		else {
			if(debug) cout << "Something went wrong. Exiting!" << endl;
			return false;
		}
	}
	// Receive and print another line
	void PrintLine() {
		char str[kBufferSize];
		char *LineText=str;
		ReadLine(LineText);
		if(debug) cout << LineText << endl;
	}

	bool get_mytanks(vector <tank_t> *AllMyTanks) {
		ReadAck();
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}
		v.clear();
		v=ReadArr();
		int i=0;
		while(v.at(0)=="mytank") {
			tank_t MyTank;
			MyTank.index=atoi(v.at(1).c_str());
			MyTank.callsign=v.at(2);
			MyTank.status=v.at(3);
			MyTank.shots_avail=atoi(v.at(4).c_str());
			MyTank.time_to_reload=atof(v.at(5).c_str());
			MyTank.flag=v.at(6);
			MyTank.pos[0]=atof(v.at(7).c_str());
			MyTank.pos[1]=atof(v.at(8).c_str());
			MyTank.angle=atof(v.at(9).c_str());
			MyTank.velocity[0]=atof(v.at(10).c_str());
			MyTank.velocity[1]=atof(v.at(11).c_str());
			MyTank.angvel=atof(v.at(12).c_str());
			AllMyTanks->push_back(MyTank);
			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			if(debug) cout << v.at(0) << endl;
			return false;
		}
		return true;
	}

	bool get_othertanks(vector <otank_t> *AllOtherTanks) {
		ReadAck();
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}
		v.clear();
		v=ReadArr();
		int i=0;
		while(v.at(0)=="othertank") {
			otank_t OtherTank;
			OtherTank.callsign=v.at(1);
			OtherTank.color=v.at(2);
			OtherTank.status=v.at(3);
			OtherTank.flag=v.at(4);
			OtherTank.pos[0]=atof(v.at(5).c_str());
			OtherTank.pos[1]=atof(v.at(6).c_str());
			OtherTank.angle=atof(v.at(7).c_str());
			AllOtherTanks->push_back(OtherTank);
			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			return false;
		}
		return true;
	}

	bool get_flags(vector <flag_t> *AllFlags) {
		ReadAck();
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}
		v.clear();
		v=ReadArr();
		int i=0;
		while(v.at(0)=="flag") {
			flag_t MyFlag;
			MyFlag.color=v.at(1);
			MyFlag.poss_color=v.at(2);
			MyFlag.pos[0]=atof(v.at(3).c_str());
			MyFlag.pos[1]=atof(v.at(4).c_str());
			AllFlags->push_back(MyFlag);
			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			return false;
		}
		return true;
	}

	bool get_shots(vector <shot_t> *AllShots) {
		ReadAck();
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}
		v.clear();
		v=ReadArr();
		int i=0;
		while(v.at(0)=="shot") {
			shot_t MyShot;
			MyShot.pos[0]=atof(v.at(1).c_str());
			MyShot.pos[1]=atof(v.at(2).c_str());
			MyShot.velocity[0]=atof(v.at(3).c_str());
			MyShot.velocity[1]=atof(v.at(4).c_str());
			AllShots->push_back(MyShot);
			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			return false;
		}
		return true;
	}

	// Commands:
	void shoot(int index) {
		// Perform a shoot request.
		char char_buff[20];
		sprintf(char_buff, " %d", index);	
		string str_buff="shoot";
		str_buff.append(char_buff);
		const char *Command = str_buff.c_str();
		SendLine(Command);
	}

	void speed(int index, double value) {
		// Set the desired speed to the specified value.
		char char_buff[20];
		sprintf(char_buff, " %d", index);	
		string str_buff="speed";
		str_buff.append(char_buff);
		sprintf(char_buff, " %f", value);
		str_buff.append(char_buff);
		const char *Command = str_buff.c_str();
		SendLine(Command);
	}

	void angvel(int index, double value) {
		// Set the desired angular velocity to the specified value.
		char char_buff[20];
		sprintf(char_buff, " %d", index);	
		string str_buff="angvel";
		str_buff.append(char_buff);
		sprintf(char_buff, " %f", value);
		str_buff.append(char_buff);
		const char *Command = str_buff.c_str();
		SendLine(Command);
	}

	void accelx(int index, double value) {
		// Set the desired accelaration in x axis to the specified value in hovertank mode.
		char char_buff[20];
		sprintf(char_buff, " %d", index);	
		string str_buff="accelx";
		str_buff.append(char_buff);
		sprintf(char_buff, " %f", value);
		str_buff.append(char_buff);
		const char *Command = str_buff.c_str();
		SendLine(Command);
	}	

	void accely(int index, double value) {
		// Set the desired accelaration in x axis to the specified value in hovertank mode.
		char char_buff[20];
		sprintf(char_buff, " %d", index);	
		string str_buff="accely";
		str_buff.append(char_buff);
		sprintf(char_buff, " %f", value);
		str_buff.append(char_buff);
		const char *Command = str_buff.c_str();
		SendLine(Command);
	}

	// Information Request:
	bool get_teams(vector <team_t> *AllTeams) {
		//Request a list of teams.
		ReadAck();
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}
		v.clear();
		v=ReadArr();
		int i=0;
		while(v.at(0)=="team") {
			team_t MyTeam;
			MyTeam.color=v.at(1);
			MyTeam.count=atoi(v.at(2).c_str());
			AllTeams->push_back(MyTeam);
			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			return false;
		}

		return get_bases(AllTeams);
	}

	bool get_bases(vector <team_t> *AllTeams){
		//Request a list of teams.
		ReadAck();
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}
		v.clear();
		v=ReadArr();
		int i=0;
		while(v.at(0)=="base") {
			
			AllTeams->at(i).base_corner[0][0]=atof(v.at(2).c_str());
			AllTeams->at(i).base_corner[0][1]=atof(v.at(3).c_str());
			AllTeams->at(i).base_corner[1][0]=atof(v.at(4).c_str());
			AllTeams->at(i).base_corner[1][1]=atof(v.at(5).c_str());
			AllTeams->at(i).base_corner[2][0]=atof(v.at(6).c_str());
			AllTeams->at(i).base_corner[2][1]=atof(v.at(7).c_str());
			AllTeams->at(i).base_corner[3][0]=atof(v.at(8).c_str());
			AllTeams->at(i).base_corner[3][1]=atof(v.at(9).c_str());

			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			return false;
		}

		return true;
	}

	bool get_obstacles(vector <obstacle_t> *AllObstacles) {
		// Request a list of obstacles.
		ReadAck();
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}
		v.clear();
		v=ReadArr();
		int i=0;
		while(v.at(0)=="obstacle") {
			obstacle_t MyObstacle;
			int j=0;
			int k=0;
			while(j+2<(int)v.size()) {
				MyObstacle.o_corner[j/2][0]=atof(v.at(j+1).c_str());
				MyObstacle.o_corner[j/2][1]=atof(v.at(j+2).c_str());
				j=j+2;
				k++;
			}
			MyObstacle.size = k;
			AllObstacles->push_back(MyObstacle);
			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			return false;
		}
		return true;
	}

	bool get_constants(vector <constant_t> *AllConstants) {
		// Request a dictionary of game constants.
		ReadAck();
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}
		v.clear();
		v=ReadArr();
		int i=0;
		while(v.at(0)=="constant") {
			constant_t MyConstant;
			MyConstant.name=v.at(1);
			MyConstant.value=v.at(2);
			AllConstants->push_back(MyConstant);
			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			return false;
		}
		return true;
	}

	bool get_occgrid(occgrid_t* occgrid){
		ReadAck();
		
		vector <string> v=ReadArr();
		if(v.at(0)!="begin") {
			return false;
		}

		v.clear();
		v=ReadArr();

		if(v.at(0)!="at") {
			return false;
		}

		size_t CurLoc = v.at(1).find(",", 0);
		occgrid->topCorner[0] = atoi(v.at(1).substr(0, CurLoc).c_str());
		occgrid->topCorner[1] = atoi(v.at(1).substr(CurLoc+1).c_str());

		v.clear();
		v=ReadArr();

		//read the size of the visible grid
		if(v.at(0)!="size") {
			return false;
		}

		CurLoc = v.at(1).find("x", 0);
		occgrid->dimensions[0] = atof(v.at(1).substr(0, CurLoc).c_str());
		occgrid->dimensions[1] = atof(v.at(1).substr(CurLoc+1).c_str());

		v.clear();
		v=ReadArr();

		occgrid->grid.clear();
		int i=0;
		while(v.at(0)!="end") {
			if(v.size() > 1) return false;
			occgrid->grid.push_back(v.at(0));
			v.clear();
			v=ReadArr();
			i++;
		}
		if(v.at(0)!="end") {
			return false;
		}
		return true;
	}

	long timer() {
	SYSTEMTIME tm;
	GetSystemTime(&tm);
	return (long)tm.wMilliseconds + 
		   (long)tm.wSecond * 1000 + 
		   (long)tm.wMinute * 60000 + 
		   (long)tm.wHour * 3600000;// + 
		   //(long)tm.wDay * 86400000;
	}

public:
	BZRC(const char *host, int port, bool debug_mode) {
		pcHost = host;
		nPort = port;
		debug = debug_mode;
		if(Init()) {
			cout << "BZRC initialization failed." << endl;
			InitStatus=false;
			Close();
		}
		else {
			InitStatus=true;
		}
	}

	// Self check
	int GetPort(){return nPort;}
	const char *GetHost() {return pcHost;}
	bool GetStatus() {return InitStatus;}

	void do_commands(vector<Command> & commands) {
		int i;
		int size = commands.size();
		World* w = World::instance();

		for (i = 0; i < size; i++) {
			Command* cmd = &commands.at(i);

			if(cmd->update() != 0){
				int info = cmd->update();
				if(info & OBSTACLES)
					SendLine("obstacles");
				if(info & MY_TANKS )
					SendLine("mytanks");
				if(info & OTHER_TANKS )
					SendLine("othertanks");
				if(info & CONSTANTS )
					SendLine("constants");
				if(info & SHOTS )
					SendLine("shots");
				if(info & FLAGS )
					SendLine("flags");
				if(info & TEAMS ){
					SendLine("teams");
					SendLine("bases");
				}

				continue;
			}

			if(cmd->occgrid()){
				char char_buff[20];
				sprintf(char_buff, " %d",  cmd->index());	
				string str_buff="occgrid";
				str_buff.append(char_buff);
		
				SendLine(str_buff.c_str());

				continue;
			}
			
			speed(cmd->index(), cmd->speed());
			angvel(cmd->index(), cmd->angvel());
			if (cmd->shoot())
				shoot(cmd->index());
		}

		for (int i = 0; i < size; i++) {
			Command* cmd = &commands.at(i);

			if(cmd->update() != 0){
				int info = cmd->update();

				if(info & OBSTACLES){
					vector<obstacle_t> obstacles;
					vector<obstacle_t>* obstacles_ptr = &obstacles;
					if (w->obstacles().size() == 0)
						obstacles_ptr = w->obstaclesP();

					get_obstacles(obstacles_ptr);
					
					vector<obstacle_t>* w_obstacles = w->obstaclesP();
					
					for (unsigned int i = 0; i < w_obstacles->size(); i++) {

						w_obstacles->at(i).size = obstacles_ptr->at(i).size;

						for (int j = 0; j < obstacles_ptr->at(i).size; j++) {
							w_obstacles->at(i).o_corner[j][0] = obstacles_ptr->at(i).o_corner[j][0];
							w_obstacles->at(i).o_corner[j][1] = obstacles_ptr->at(i).o_corner[j][1];
						}
					}
				}
				if(info & MY_TANKS ){
					vector<tank_t> tanks;
					vector<tank_t>* tanks_ptr = &tanks;
					if (w->tanks().size() == 0)
						tanks_ptr = w->tanksP();

					get_mytanks(tanks_ptr);
					vector<tank_t>* w_tanks = w->tanksP();
					for (unsigned int i = 0; i < w_tanks->size(); i++) {
						w_tanks->at(i).angle = tanks_ptr->at(i).angle;
						w_tanks->at(i).angvel = tanks_ptr->at(i).angvel;
						w_tanks->at(i).callsign = tanks_ptr->at(i).callsign;
						w_tanks->at(i).flag = tanks_ptr->at(i).flag;
						w_tanks->at(i).index = tanks_ptr->at(i).index;
						w_tanks->at(i).pos[0] = tanks_ptr->at(i).pos[0];
						w_tanks->at(i).pos[1] = tanks_ptr->at(i).pos[1];
						w_tanks->at(i).shots_avail = tanks_ptr->at(i).shots_avail;
						w_tanks->at(i).status = tanks_ptr->at(i).status;
						w_tanks->at(i).time_to_reload = tanks_ptr->at(i).time_to_reload;
						w_tanks->at(i).velocity[0] = tanks_ptr->at(i).velocity[0];
						w_tanks->at(i).velocity[1] = tanks_ptr->at(i).velocity[1];
					}

				}
				if(info & OTHER_TANKS ){
					vector<otank_t> otanks;
					vector<otank_t>* otanks_ptr = &otanks;
					if (w->other_tanks().size() == 0)
						otanks_ptr = w->other_tanksP();

					get_othertanks(otanks_ptr);
					vector<otank_t>* w_otanks = w->other_tanksP();
					for (unsigned int i = 0; i < w_otanks->size(); i++) {
						w_otanks->at(i).angle = otanks_ptr->at(i).angle;
						w_otanks->at(i).callsign = otanks_ptr->at(i).callsign;
						w_otanks->at(i).color = otanks_ptr->at(i).color;
						w_otanks->at(i).flag = otanks_ptr->at(i).flag;
						w_otanks->at(i).pos[0] = otanks_ptr->at(i).pos[0];
						w_otanks->at(i).pos[1] = otanks_ptr->at(i).pos[1];
						w_otanks->at(i).status = otanks_ptr->at(i).status;
					}
				}
				if(info & CONSTANTS ){
					w->constantsP()->clear();
					get_constants(w->constantsP());
				}
				if(info & SHOTS ){
					w->shotsP()->clear();
					get_shots(w->shotsP());
				}
				if(info & FLAGS ){
					w->flagsP()->clear();
					get_flags(w->flagsP());
				}
				if(info & TEAMS ){
					vector<team_t> teams;
					vector<team_t>* teams_ptr = &teams;
					if (w->teams().size() == 0)
						teams_ptr = w->teamsP();

					get_teams(teams_ptr);
					vector<team_t>* w_teams = w->teamsP();
					for (unsigned int i = 0; i < w_teams->size(); i++) {

						for (int j = 0; j < 4; j++) {
							w_teams->at(i).base_corner[j][0] = teams_ptr->at(i).base_corner[j][0];
							w_teams->at(i).base_corner[j][1] = teams_ptr->at(i).base_corner[j][1];
						}

						w_teams->at(i).color = teams_ptr->at(i).color;
						w_teams->at(i).count = teams_ptr->at(i).count;
					}
				}

				continue;
			}

			if(cmd->occgrid()){
				get_occgrid(&w->occgridsP()->at(cmd->index()));
				continue;
			}

			// read response for speed
			ReadAck();
			ReadBool();

			// read response for angvel
			ReadAck();
			ReadBool();

			// read response for shoot
			if (cmd->shoot()) {
				ReadAck();
				ReadBool();
			}
		}
	}

	void get_lots_o_stuff(
		vector <tank_t> *mytanks,
		vector <otank_t> *otanks,
		vector <flag_t> *flags,
		vector <shot_t> *shots) {
		
		SendLine("mytanks");
		SendLine("othertanks");
		SendLine("flags");
		SendLine("shots");

		get_mytanks(mytanks);
		get_othertanks(otanks);
		get_flags(flags);
		get_shots(shots);
	}

	int Close() {
		closesocket(sd);
		WSACleanup();
		return 0;
	}

};

#endif